﻿using System;
using System.ComponentModel;
using ExFlash.Records;

namespace ExFlash.Tags
{
    public class DefineFont2Tag : DefineFontTag
    {
        public Boolean FontFlagsHasLayout
        {
            get;
            protected set;
        }

        public Boolean FontFlagsShiftJIS
        {
            get;
            protected set;
        }
        
        public Boolean FontFlagsSmallText
        {
            get;
            protected set;
        }        

        public Boolean FontFlagsANSI
        {
            get;
            protected set;
        }

        public Boolean FontFlagsWideOffsets
        {
            get;
            protected set;
        }

        public Boolean FontFlagsWideCodes
        {
            get;
            protected set;
        }

        public Boolean FontFlagsItalic
        {
            get;
            protected set;
        }

        public Boolean FontFlagsBold
        {
            get;
            protected set;
        }

        public LangCode LanguageCode
        {
            get;
            protected set;
        }

        [Browsable(false)]
        public Byte FontNameLen
        {
            get;
            protected set;
        }

        public Byte[] FontName
        {
            get;
            protected set;
        }
        
        public uint CodeTableOffset
        {
            get;
            protected set;
        }

        public ushort[] CodeTable
        {
            get;
            protected set;
        }

        public short FontAscent
        {
            get;
            protected set;
        }

        public short FontDescent
        {
            get;
            protected set;
        }

        public short FontLeading
        {
            get;
            protected set;
        }

        public short[] FontAdvanceTable
        {
            get;
            protected set;
        }

        public RectangleRecord[] FontBoundsTable
        {
            get;
            protected set;
        }

        public ushort KerningCount
        {
            get;
            protected set;
        }

        public KerningRecord[] FontKerningTable
        {
            get;
            protected set;
        }
        
        public DefineFont2Tag(int len, int offset)
            : this(TagCodes.DefineFont2, len, offset)
        {

        }

        protected DefineFont2Tag(TagCodes code, int len, int offset)
            : base(code, len, offset)
        {

        }

        public override void SwfDeserialize(BinaryBitReader reader)
        {
            long startIndex = reader.Position;

            FontID = reader.ReadUInt16();

            FontFlagsHasLayout = reader.ReadBoolean();
            FontFlagsShiftJIS = reader.ReadBoolean();
            FontFlagsSmallText = reader.ReadBoolean();
            FontFlagsANSI = reader.ReadBoolean();
            FontFlagsWideOffsets = reader.ReadBoolean();
            FontFlagsWideCodes = reader.ReadBoolean();
            FontFlagsItalic = reader.ReadBoolean();
            FontFlagsBold = reader.ReadBoolean();

            reader.AlignBits();

            LanguageCode = (LangCode)reader.ReadByte();

            FontNameLen = reader.ReadByte();

            FontName = new Byte[FontNameLen];
            reader.Read(FontName, 0, FontNameLen);

            NumGylphs = reader.ReadUInt16();

            // For some reason, even if the gylph number is zero, there is trailing data. 
            // So we cheat and skip it.
            if (NumGylphs == 0 && reader.Position - startIndex != TagLength)
            {
                reader.Position = startIndex + TagLength;
                return;
            }

            OffsetTable = new uint[NumGylphs];
            GylphShapeTable = new Shape[NumGylphs];
            CodeTable = new ushort[NumGylphs];

            if (FontFlagsWideOffsets)
            {
                for (int i = 0; i < NumGylphs; i++)
                {
                    OffsetTable[i] = reader.ReadUInt32();
                }

                if (NumGylphs > 0)
                {
                    CodeTableOffset = reader.ReadUInt32();
                }
            }
            else
            {
                for (int i = 0; i < NumGylphs; i++)
                {
                    OffsetTable[i] = reader.ReadUInt16();
                }
                if (NumGylphs > 0)
                {
                    CodeTableOffset = reader.ReadUInt16();
                }
            }

            uint ShapeStart = OffsetTable[0];
            long StartPos = reader.Position;

            for (int i = 0; i < NumGylphs; i++)
            {
                if (reader.Position - StartPos != OffsetTable[i] - OffsetTable[0])
                {
                    int j = 4;
                }
                GylphShapeTable[i] = new Shape(ShapeType.Shape1);
                GylphShapeTable[i].SwfDeserialize(reader);
            }

            if (FontFlagsWideCodes)
            {
                for (int i = 0; i < NumGylphs; i++)
                {
                    CodeTable[i] = reader.ReadUInt16();
                }
            } 
            else
            {
                for (int i = 0; i < NumGylphs; i++)
                {
                    CodeTable[i] = reader.ReadByte();
                }
            }

            if (FontFlagsHasLayout)
            {
                FontAscent = reader.ReadInt16();
                FontDescent = reader.ReadInt16();
                FontLeading = reader.ReadInt16();

                FontAdvanceTable = new short[NumGylphs];
                FontBoundsTable = new RectangleRecord[NumGylphs];

                for (int i = 0; i < NumGylphs; i++)
                {
                    FontAdvanceTable[i] = reader.ReadInt16();
                }

                for (int i = 0; i < NumGylphs; i++)
                {
                    FontBoundsTable[i] = new RectangleRecord();
                    FontBoundsTable[i].SwfDeserialize(reader);
                }

                KerningCount = reader.ReadUInt16();

                FontKerningTable = new KerningRecord[KerningCount];

                for (int i = 0; i < KerningCount; i++)
                {
                    FontKerningTable[i] = new KerningRecord(FontFlagsWideCodes);
                    FontKerningTable[i].SwfDeserialize(reader);
                }
            }
        }

        public override void SwfSerialize(byte[] arr, ref int offset)
        {
            throw new NotImplementedException();
        }
    }
}
